<?php

/**
 * 
 * ClientEngage: ClientEngage Visitor Voice (http://www.clientengage.com)
 * Copyright 2012, ClientEngage (http://www.clientengage.com)
 *
 * You must have purchased a valid license from CodeCanyon in order to have 
 * the permission to use this file.
 * 
 * You may only use this file according to the respective licensing terms 
 * you agreed to when purchasing this item on CodeCanyon.
 * 
 * 
 * 
 *
 * @author          ClientEngage <contact@clientengage.com>
 * @copyright       Copyright 2013, ClientEngage (http://www.clientengage.com)
 * @link            http://www.clientengage.com ClientEngage
 * @since           ClientEngage - Visitor Voice v 1.0
 * 
 */
App::uses('AppController', 'Controller');

/**
 * Visitorforms Controller
 *
 * @property Visitorform $Visitorform
 * @property Securimage $captcha
 */
class VisitorformsController extends AppController
{

    public $name = 'Visitorforms';

    /**
     * Controllers to be loaded
     * @var array
     */
    public $components = array('Security');

    /**
     * Processes visitorform submissions
     * @param string $slug The unique slug of the visitorform
     * @throws NotFoundException
     */
    public function get($slug = null)
    {
        $this->layout = 'form';

        if (!($visitorform = $this->Visitorform->find('first', array(
            'conditions' => array('Visitorform.slug' => $slug, 'Visitorform.archived' => false),
            'contain' => array('Field' => array('FieldOption'), 'Formtheme')))))
        {
            throw new NotFoundException(__('Invalid Visitor Form'));
        }

        $this->set('title_for_layout', $visitorform['Visitorform']['title']);

        if ($this->request->is('post'))
        {
            $visitorvoice = array();
            $visitorvoice['Visitorvoice'] = array(
                'visitorform_id' => $visitorform['Visitorform']['id'],
                'referer' => $this->request->data['Visitorvoice']['referer'],
                'started' => $this->request->data['Visitorvoice']['started'],
                'useragent' => env('HTTP_USER_AGENT')
            );
            $visitorvoice['Response'] = $this->request->data['Response'];

            $this->Visitorform->Visitorvoice->data = $visitorvoice;

            if ($this->Visitorform->Visitorvoice->validateAssociated($visitorvoice))
            {
                if ($this->__validateFields($visitorvoice, $visitorform))
                {
                    /* $this->Visitorform->Visitorvoice->saveVisitorvoice($visitorvoice);
                      $this->Visitorform->Visitorvoice->saveVisitorvoice($visitorvoice);
                      $this->Visitorform->Visitorvoice->saveVisitorvoice($visitorvoice);
                      $this->Visitorform->Visitorvoice->saveVisitorvoice($visitorvoice);
                      $this->Visitorform->Visitorvoice->saveVisitorvoice($visitorvoice);
                      $this->Visitorform->Visitorvoice->saveVisitorvoice($visitorvoice); */
                    $this->Visitorform->Visitorvoice->saveVisitorvoice($visitorvoice);
                    $this->redirect(array('action' => 'success', $slug));
                }
                else
                {
                    $this->Session->setFlash($visitorform['Visitorform']['error_message'], 'flashmessages/frontend');
                }
            }
        }

        if (isset($this->request->params['named']['ref']))
            $this->set('referer', base64_decode($this->request->params['named']['ref']));
        else
            $this->set('referer', ($this->referer() == '/' ? null : $this->referer()));

        $this->set('visitorform', $visitorform);
        $this->set('title_for_layout', $visitorform['Visitorform']['title']);
        unset($this->request->data['Visitorform']['captcha']);
    }

    /**
     * Renders the success page after a form submission
     * @param string $slug The unique slug of teh visitorform
     * @throws NotFoundException
     */
    public function success($slug = null)
    {
        $this->layout = 'form';

        if (!($visitorform = $this->Visitorform->find('first', array(
            'conditions' => array('Visitorform.slug' => $slug, 'Visitorform.archived' => false),
            'contain' => array('Formtheme')))))
        {
            throw new NotFoundException(__('Invalid Visitor Form'));
        }

        $this->set('title_for_layout', $visitorform['Visitorform']['title']);
        $this->set('visitorform', $visitorform);
    }

    /**
     * Takes a submitted request and checks if the form responses validate 
     * against each field's specific validation rule(s)
     * @param array $visitorvoice The response data to be checked
     * @param array $visitorform The form to which the response data belongs
     * @return bool Success
     */
    private function __validateFields($visitorvoice = array(), $visitorform = array())
    {
        $this->__pairResponseToField($visitorvoice, $visitorform);

        $validateCaptcha = Hash::check($visitorform, 'Field.{n}[type=captcha]');
        if ($validateCaptcha === true && (!isset($this->request->data['Visitorform']['captcha']) || ($this->request->data['Visitorform']['captcha'] == $this->Session->read('captcha')) === false))
        {
            $captchaField = Hash::extract($visitorform, 'Field.{n}[type=captcha]');
            $this->Visitorform->validationErrors['captcha']['validCaptcha'] = $captchaField[0]['required_message'];
        }
        else
        {
            $this->Session->delete('captcha');
        }

        // Check required fields
        foreach ($visitorvoice['Response'] as $k => $response)
        {
            if ($response['Field']['required'] === true)
            {
                if (in_array($response['Field']['type'], array('textshort', 'textlong', 'checkbox', 'rating', 'slider', 'spinner', 'date')) && trim($response['Response']['value']) == '')
                {
                    $this->Visitorform->Visitorvoice->Response->validationErrors[$k]['value']['required'] = $response['Field']['required_message']; // Value
                }
                if (in_array($response['Field']['type'], array('checkbox')) && $response['Response']['value'] == false)
                {
                    $this->Visitorform->Visitorvoice->Response->validationErrors[$k]['value']['required'] = $response['Field']['required_message']; // Value
                }
                if (in_array($response['Field']['type'], array('select', 'radio')) && (!isset($response['Response']['field_option_id']) || trim($response['Response']['field_option_id']) == ''))
                {
                    $this->Visitorform->Visitorvoice->Response->validationErrors[$k]['field_option_id']['required'] = $response['Field']['required_message']; // Value
                }
                if (in_array($response['Field']['type'], array('selectmultiple', 'checkboxmultiple')) && empty($response['FieldOption']))
                {
                    $this->Visitorform->Visitorvoice->Response->validationErrors[$k]['FieldOption']['required'] = $response['Field']['required_message']; // Value
                }
            }

            // Check data types & validate
            if (in_array($response['Field']['type'], array('rating', 'slider', 'spinner')) && trim($response['Response']['value']) != '')
            {
                if (!is_numeric($response['Response']['value'])) // not numerical
                    $this->Visitorform->Visitorvoice->Response->validationErrors[$k]['value']['numerical'] = __('Please enter a valid integer'); // Value
                else
                {
                    if ($response['Field']['custom_min'] !== null && ($response['Response']['value'] < $response['Field']['custom_min']))
                        $this->Visitorform->Visitorvoice->Response->validationErrors[$k]['value']['minInvalid'] = String::insert(__('Please enter a value that is equal to or greater than :val'), array('val' => $response['Field']['custom_min'])); // Value
                    if ($response['Field']['custom_max'] !== null && ($response['Response']['value'] > $response['Field']['custom_max']))
                        $this->Visitorform->Visitorvoice->Response->validationErrors[$k]['value']['maxInvalid'] = String::insert(__('Please enter a value that is equal to or smaller than :val'), array('val' => $response['Field']['custom_max'])); // Value
                }
            }
        }

        // Validate regex rules
        foreach ($visitorvoice['Response'] as $k => $response)
        {
            if ($response['Field']['validation_regex'] != null && in_array($response['Field']['type'], array('textshort', 'textlong', 'checkbox')))
            {
                if (!preg_match($response['Field']['validation_regex'], $response['Response']['value']))
                {
                    $this->Visitorform->Visitorvoice->Response->validationErrors[$k]['value']['regex'] = $response['Field']['validation_message']; // Value
                }
            }
        }

        return empty($this->Visitorform->Visitorvoice->Response->validationErrors) && empty($this->Visitorform->validationErrors);
    }

    /**
     * Pairs the fields to a visitorvoice array to be able to check all 
     * validation rules are passing
     * @param array $visitorvoice The submitted 
     * @param array $visitorform The visitorform containing all fields
     */
    private function __pairResponseToField(&$visitorvoice = array(), $visitorform = array())
    {
        foreach ($visitorvoice['Response'] as $k => $response)
        {
            foreach ($visitorform['Field'] as $field)
            {
                if ($field['id'] == $response['Response']['field_id'])
                {
                    $visitorvoice['Response'][$k]['Field'] = $field;
                }
            }
        }
    }

    /**
     * Renders JavaScript returned to including web-pages
     * @param string $slug The unique slug of the visitorform
     * @throws NotFoundException
     */
    public function code($slug = null)
    {
        $this->layout = 'plain';
        $this->response->type('js');

        if (strpos($slug, '.js') === false)
        {
            throw new NotFoundException(__('Invalid Visitor Form'));
        }

        $slug = str_replace('.js', '', $slug);
        if (!($visitorform = $this->Visitorform->find('first', array(
            'conditions' => array('Visitorform.slug' => $slug, 'Visitorform.archived' => false)))))
        {
            throw new NotFoundException(__('Invalid Visitor Form'));
        }

        $this->set('slug', $slug);
        $this->set('referer', $this->referer());
        $this->set('visitorform', $visitorform);
    }

    /**
     * Renders the Buttom Template CSS styles
     * @param string $slug The unique slug of the visitorform
     * @throws NotFoundException
     */
    public function css($slug = null)
    {
        $this->layout = 'plain';
        $this->response->type('css');

        if (strpos($slug, '.css') === false)
        {
            throw new NotFoundException(__('Invalid Visitor Form'));
        }

        $slug = str_replace('.css', '', $slug);
        if (!($visitorform = $this->Visitorform->find('first', array(
            'conditions' => array('Visitorform.slug' => $slug, 'Visitorform.archived' => false),
            'fields' => array('id', 'slug', 'active'),
            'contain' => array('Buttontheme' => array('fields' => array('css')))))))
        {
            throw new NotFoundException(__('Invalid Visitor Form'));
        }

        $this->set('visitorform', $visitorform);
    }

    /**
     * Renders captcha images
     * @param int $rand Random number
     */
    public function simage($rand = null)
    {
        $this->autoRender = false;

        App::import('Vendor', 'captcha/captcha');
        $captcha = new captcha();
        $captcha->show_captcha();
        die;
    }

    public function beforeFilter()
    {
        parent::beforeFilter();
        $this->Security->blackHoleCallback = 'blackhole';
        $this->Auth->allow('get', 'success', 'code', 'css', 'simage', 'saudio');
    }

    public function blackhole($type)
    {
        
    }

    /**
     * Lists available visitorforms
     */
    public function admin_index()
    {
        $this->set('title_for_layout', __('Visitorforms'));

        $conditions = array('Visitorform.archived' => false);
        if (isset($this->request->params['named']['archived']) && $this->request->params['named']['archived'] == true)
            $conditions = Hash::merge($conditions, array('Visitorform.archived' => true));
        if (isset($this->request->params['named']['running']) && $this->request->params['named']['running'] == true)
            $conditions = Hash::merge($conditions, array('Visitorform.visitorvoice_count > ' => 0));
        else
            $conditions = Hash::merge($conditions, array('Visitorform.visitorvoice_count = ' => 0));

        $this->Visitorform->recursive = 0;
        $this->set('visitorforms', $this->paginate('Visitorform', $conditions));
    }

    /**
     * Lists currently active visitorforms
     */
    public function admin_responses()
    {
        $this->set('title_for_layout', __('Active Visitorforms'));

        $conditions = array('Visitorform.visitorvoice_count > ' => 0, 'Visitorform.archived' => false);
        if (isset($this->request->params['named']['archived']) && $this->request->params['named']['archived'] == true)
            $conditions = array_merge($conditions, array('Visitorform.archived' => true));

        $this->Visitorform->recursive = 0;
        $this->set('visitorforms', $this->paginate('Visitorform', $conditions));
    }

    /**
     * view method
     *
     * @throws NotFoundException
     * @param string $id
     * @return void
     */
    public function admin_view($id = null)
    {
        $this->set('title_for_layout', __('View Visitorform'));

        $this->Visitorform->id = $id;
        $this->Visitorform->recursive = 2;
        if (!$this->Visitorform->exists())
        {
            throw new NotFoundException(__('Invalid Visitor Form'));
        }
        $this->set('visitorform', $this->Visitorform->find('first', array('conditions' => array('Visitorform.id' => $id), 'contain' => array('Field' => 'FieldOption', 'Formtheme' => array('id', 'title'), 'Buttontheme' => array('id', 'title')))));
    }

    /**
     * add method
     *
     * @return void
     */
    public function admin_add()
    {
        $this->set('title_for_layout', __('Create Visitorform'));


        if ($this->request->is('post'))
        {
            $this->Visitorform->create();
            if ($this->Visitorform->save($this->request->data))
            {
                $this->Session->setFlash(__('The Visitor Form has been saved'), Flash::Success);
                $this->redirect(array('action' => 'view', $this->Visitorform->id));
            }
            else
            {
                $this->Session->setFlash(__('The Visitor Form could not be saved. Please, try again.'), Flash::Warning);
            }
        }

        $this->set('buttonthemes', $this->Visitorform->Buttontheme->find('list'));
        $this->set('formthemes', $this->Visitorform->Formtheme->find('list'));
    }

    /**
     * edit method
     *
     * @throws NotFoundException
     * @param string $id
     * @return void
     */
    public function admin_edit($id = null)
    {
        $this->set('title_for_layout', __('Edit Visitorform'));

        $this->Visitorform->id = $id;
        if (!$this->Visitorform->exists())
        {
            throw new NotFoundException(__('Invalid Visitor Form'));
        }
        if ($this->request->is('post') || $this->request->is('put'))
        {
            if ($this->Visitorform->save($this->request->data))
            {
                $this->Session->setFlash(__('The Visitor Form has been saved'), Flash::Success);
                $this->redirect(array('action' => 'view', $this->Visitorform->id));
            }
            else
            {
                $this->Session->setFlash(__('The Visitor Form could not be saved. Please, try again.'), Flash::Warning);
            }
        }
        else
        {
            $this->request->data = $this->Visitorform->find('first', array('conditions' => array('Visitorform.id' => $id)));
        }

        $this->set('buttonthemes', $this->Visitorform->Buttontheme->find('list'));
        $this->set('formthemes', $this->Visitorform->Formtheme->find('list'));

        $this->set(compact('users'));
    }

    /**
     * delete method
     *
     * @throws MethodNotAllowedException
     * @throws NotFoundException
     * @param string $id
     * @return void
     */
    public function admin_delete($id = null)
    {
        if (!$this->request->is('post'))
        {
            throw new MethodNotAllowedException();
        }
        $this->Visitorform->id = $id;
        if (!$this->Visitorform->exists())
        {
            throw new NotFoundException(__('Invalid Visitor Form'));
        }
        if ($this->Visitorform->delete())
        {
            $this->Session->setFlash(__('Visitor Form deleted'), Flash::Success);
            $this->redirect(array('action' => 'index'));
        }
        $this->Session->setFlash(__('Visitor Form was not deleted'), Flash::Error);
        $this->redirect(array('action' => 'index'));
    }

    public function beforeRender()
    {
        parent::beforeRender();
    }

    /**
     * Handles the activation/deactivation of visitor forms
     * @param uuid $id Visitorform ID
     * @throws NotFoundException
     */
    public function admin_activate($id = null)
    {

        $this->Visitorform->id = $id;
        if (!$this->Visitorform->exists())
        {
            throw new NotFoundException(__('Invalid Visitor Form'));
        }

        $activate = $this->request->params['named']['type'] == 'activate' ? true : false;

        if ($this->Visitorform->saveField('active', $activate))
        {
            if ($activate)
                $this->Session->setFlash(__('The Visitor Form was successfully activated'), Flash::Success);
            else
                $this->Session->setFlash(__('The Visitor Form was successfully deactivated'), Flash::Success);
        }
        else
        {
            if ($activate)
                $this->Session->setFlash(__('The Visitor Form could not be activated'), Flash::Error);
            else
                $this->Session->setFlash(__('The Visitor Form could not be deactivated'), Flash::Error);
        }

        $this->redirect($this->referer());
    }

    /**
     * Handles the duplication of visitor forms
     * @param uuid $id
     * @throws MethodNotAllowedException
     * @throws NotFoundException
     */
    public function admin_duplicate($id = null)
    {
        if (!$this->request->is('post'))
        {
            throw new MethodNotAllowedException();
        }
        $this->Visitorform->id = $id;
        if (!$this->Visitorform->exists())
        {
            throw new NotFoundException(__('Invalid Visitor Form'));
        }
        if ($this->Visitorform->duplicate($id))
        {
            $this->Session->setFlash(__('Visitor Form duplicated'), Flash::Success);
            $this->redirect(array('action' => 'view', $this->Visitorform->id));
        }
        $this->Session->setFlash(__('Visitor Form was not duplicated'), Flash::Error);
        $this->redirect($this->referer());
    }

}
